#include "Thread.hpp"
#include "BlockQueue.hpp"
#include <vector>
#include <cstdlib>
#include <ctime>
#include "Task.hpp"
using namespace ThreadModule;


using  blockqueue_t = BlockQueue<Task>;

void PrintHello()
{
    std::cout << "hello world" << std::endl;
}
class ThreadData
{
    public:
    ThreadData(blockqueue_t & bq,std::string name)
    :_bq(bq),who(name)
    {}

    blockqueue_t &_bq;
    std::string who;
};

void Consumer(ThreadData* td)
{
    while(1)
    {
        sleep(1);
        //1.从阻塞队列中取一个任务
        Task t;
        td->_bq.Pop(&t);

        //2.处理这个任务
        t();
        //std::cout << "Consumer Task" << t.ResultToString() << std::endl;
    }
}
void Product(ThreadData* td)
{
    srand(time(nullptr)^ pthread_self());
    while(1)
    {
        sleep(1);
        // //1.生成任务
        // int a = rand() % 10 +1;
        // usleep(1000);
        // int b = rand() % 20 + 1;
        // Task t(a,b);
        Task t = PrintHello;
        //2.把任务放到阻塞队列中
        td->_bq.Enqueue(t);
        //std::cout << "Product Task" << t.DebugToString() << std::endl;
    }
}

void StartConsumer(std::vector<Thread<ThreadData*>> * threads,int num,blockqueue_t& bq)
{
    for(int i = 0;i < num; ++i)
    {
        std::string name = "thread-" + std::to_string(i+1);
        ThreadData* td = new ThreadData(bq,name);
        threads->emplace_back(Consumer,td,name);
        threads->back().Start();//每新建一个线程就启动它
    }
}
void StartProductor(std::vector<Thread<ThreadData*>> * threads,int num,blockqueue_t& bq)
{
    for(int i = 0;i < num; ++i)
    {
        std::string name = "thread-" + std::to_string(i+1);
        ThreadData* td = new ThreadData(bq,name);

        threads->emplace_back(Product,td,name);
        threads->back().Start();//每新建一个线程就启动它
    }
}
void WaitAllThread(std::vector<Thread<ThreadData*>>&  threads)
{
    for(auto& e : threads)
    {
        e.Join();
    }
}

int main()
{
    blockqueue_t* bq = new blockqueue_t(5);//队列最多有五个数据
    std::vector<Thread<ThreadData*>> threads;
    StartConsumer(&threads,1,*bq);
    StartProductor(&threads,1,*bq);
    WaitAllThread(threads);

}


